<template>
  <view>
    <view class="edgeInsetTop"></view>
    <view @touchstart="hideDrawer">
      <scroll-view
        class="cu-chat"
        :scroll-y="true"
        :scroll-with-animation="scrollAnimation"
        :scroll-top="scrollTop"
        :scroll-into-view="scrollToView"
        @scrolltoupper="loadHistory"
        upper-threshold="50"
      >
        <!-- 加载历史数据 -->
        <u-loading-icon :show="isHistoryLoading" />
        <view v-for="(row, index) in msgList" :key="index" :id="'msg' + row.id">
          <view v-if="row.type == 'chat'">
            <view class="cu-item self" v-if="row.to_id == to_id">
              <!-- 文字消息 -->
              <view class="main" v-if="row.message.type == 'text'">
                <view class="content bg-green">
                  <rich-text :nodes="row.message.content.text" />
                </view>
              </view>
              <!-- 图片消息 -->
              <view class="main" v-if="row.message.type == 'img'">
                <u-image
                  :src="row.message.content.url"
                  @click="showPic(row.message)"
                  :width="row.message.content.w + 'px'"
                  :height="row.message.content.h + 'px'"
                />
              </view>
              <!-- 语音消息 -->
              <view
                class="main"
                v-if="row.message.type == 'voice'"
                @click="playVoice(row)"
                :class="{ play: playMsgid == row.id }"
              >
                <view class="action"> {{ row.message.content.length }}" </view>
                <view class="content bg-green">
                  <text :style="{ width: row.message.content.length * 6 + 'rpx' }"></text>
                  <u-icon name="volume-fill" color="#fff" />
                </view>
              </view>
              <!-- 商品消息-->
              <view class="main goods" v-if="row.message.type == 'goods'">
                <view class="content" @click="onGoods(goods.id)">
                  <u-image
                    :show-menu-by-longpress="false"
                    :src="$imageOss(row.message.content.image, 100, 0)"
                    mode="widthFix"
                    width="400rpx"
                    height="auto"
                  />
                  <view class="text-price">
                    {{ row.message.content.price }}
                  </view>
                  <view class="text-name">
                    {{ row.message.content.title }}
                  </view>
                </view>
              </view>
              <!-- 头像 -->
              <u-avatar
                :src="$imageOss(row.form.avatar, 100, 100)"
                shape="square"
                size="41"
              />
              <view class="date">{{ $timeToChat(row.createtime) }}</view>
            </view>
            <view class="cu-item" v-else>
              <u-avatar
                :src="$imageOss(row.form.avatar, 100, 100)"
                shape="square"
                size="41"
              />
              <!-- 文字消息 -->
              <view class="main" v-if="row.message.type == 'text'">
                <view class="content">
                  <rich-text :nodes="row.message.content.text" />
                </view>
              </view>
              <!-- 图片消息 -->
              <view class="main" v-if="row.message.type == 'img'">
                <u-image
                  :src="row.message.content.url"
                  @click="showPic(row.message)"
                  :width="row.message.content.w + 'px'"
                  :height="row.message.content.h + 'px'"
                />
              </view>
              <!-- 语音消息 -->
              <view
                class="main"
                v-if="row.message.type == 'voice'"
                @click="playVoice(row)"
                :class="{ play: playMsgid == row.id }"
              >
                <view class="content">
                  <u-icon name="volume-fill" color="#fff" />
                  <text :style="{ width: row.message.content.length * 6 + 'rpx' }"></text>
                </view>
                <view class="action"> {{ row.message.content.length }}" </view>
              </view>
              <view class="date">{{ $timeToChat(row.createtime) }}</view>
            </view>
          </view>
          <view v-if="row.type == 'sys'">
            <!-- 系统消息 -->
            <view class="cu-info">对方撤回一条消息!</view>
          </view>
        </view>
      </scroll-view>
    </view>
    <!-- 抽屉栏 -->
    <view
      class="popup-layer"
      :class="{ showLayer: popupLayerClass }"
      @touchmove.stop.prevent="discard"
    >
      <!-- 表情 -->
      <view :class="{ hidden: hideEmoji }">
        <view class="emoji">
          <scroll-view class="emojinav" scroll-x scroll-with-animation>
            <view class="item">
              <view
                :class="{ emojibg: item == TabCur }"
                v-for="(item, index) in emojiList.categories"
                :key="index"
                @click="tabSelect"
                :data-id="item"
                :style="{ backgroundImage: 'url(' + emojiList.groups[item][0].url + ')' }"
              ></view>
            </view>
          </scroll-view>
          <!-- 列表 -->
          <scroll-view
            v-for="(emoji, groups) in emojiList.groups"
            :key="groups"
            v-if="TabCur == groups"
            class="subject"
            scroll-y
            scroll-with-animation
          >
            <view class="item">
              <view
                v-for="(item, index) in emoji"
                :key="index"
                @click="addEmoji(item.value)"
                :style="{ backgroundImage: 'url(' + item.url + ')' }"
              ></view>
            </view>
          </scroll-view>
        </view>
      </view>
      <!-- 更多功能 -->
      <view class="solid-top" :class="{ hidden: hideMore }">
        <view class="opmenu solid-top">
          <view class="box" @click="getImage('camera')">
            <view class="icon">
              <u-icon name="camera-fill" size="35" color="#828282" />
            </view>
            <text class="text-sm">拍摄</text>
          </view>
          <view class="box" @click="getImage('album')">
            <view class="icon">
              <u-icon name="photo-fill" size="35" color="#828282" />
            </view>
            <text class="text-sm">照片</text>
          </view>
        </view>
      </view>
    </view>
    <!-- 底部输入栏 -->
    <view
      class="input-box"
      :class="{ emptybottom: emptybottom, showLayer: popupLayerClass }"
      @touchmove.stop.prevent="discard"
    >
      <view class="voice">
        <u-icon
          :name="isVoice ? 'edit-pen' : 'mic'"
          size="28"
          color="#818181"
          @click="switchVoice"
        />
      </view>
      <view class="textbox">
        <view
          class="voice-mode"
          :class="{ hidden: !isVoice, recording: recording }"
          @touchstart="voiceBegin"
          @touchmove.stop.prevent="voiceIng"
          @touchend="voiceEnd"
          @touchcancel="voiceCancel"
        >
          {{ voiceTis }}
        </view>
        <view class="text-mode" :class="{ hidden: isVoice }">
          <view class="box">
            <textarea
              auto-height="true"
              maxlength="300"
              :show-confirm-bar="false"
              cursor-spacing="90"
              v-model="textMsg"
              @focus="textareaFocus"
              @blur="textareaBlur"
              @confirm="sendText"
            />
          </view>
          <view class="em" @click="chooseEmoji">
            <u-image
              :src="require('@/static/mall/emoji.png')"
              width="26px"
              height="26px"
            />
          </view>
        </view>
      </view>
      <view class="more" @click="showMore" style="margin-right: -12rpx">
        <u-icon name="plus-circle" size="28" color="#323232" />
      </view>
      <view class="send" :class="{ hidden: isVoice }">
        <text
          class="fasong"
          v-if="textMsg"
          @click="sendText"
          style="background-color: #3ba199"
          >发送</text
        >
        <text class="fasong" v-else>发送</text>
      </view>
    </view>
    <!-- 商品进入弹窗 -->
    <view class="chatTips" v-if="goods && isGoods">
      <image :src="$imageOss(goods.image, 100, 100)" mode="aspectFill" />
      <view class="details">
        <view>
          <u-text :text="goods.title" size="14px" lines="1" />
          <u-icon name="close" size="20" @click="closeTips" />
        </view>
        <view>
          <view class="text-lg text-orange">
            <text class="text-price">{{ goods.price }}</text>
          </view>
          <view>
            <button class="cu-btn" @click="sendGoods(goods)">发送商家</button>
          </view>
        </view>
      </view>
    </view>
    <!-- 录音UI效果 -->
    <view class="record" :class="{ hidden: !recording }">
      <view class="ing" :class="{ hidden: willStop }">
        <u-icon name="mic" size="50" color="#3BA199" />
      </view>
      <view class="cancel" :class="{ hidden: !willStop }">
        <u-icon name="mic-off" size="50" color="#3BA199" />
      </view>
      <view class="tis" :class="{ change: willStop }">{{ recordTis }}</view>
    </view>
  </view>
</template>
<script>
const emotions = require("@/static/mall/emotions.json");
import { commonUpload } from "@/request/common.js";
import { chatHistory, chatShopChat, chatSend } from "@/request/chat.js";
export default {
  data() {
    return {
      user_id: "", // 本人ID
      avatar: "", // 本人头像
      nickname: "", // 本人昵称
      to_id: 0, // 商家ID
      shop_id: 0, // 店铺ID
      shop_name: null, // 店铺名称
      shop_avatar: null, // 店铺头像
      textMsg: "", //文字消息
      isHistoryLoading: false, // 是否加载历史记录
      reload: false,
      current_page: 1, // 消息页数
      scrollAnimation: false, // 滑动动画
      scrollTop: 0, // 滑动位置距离
      scrollToView: "", // 滑动位置元素
      msgList: [], // 所有消息列表
      msgImgList: [], // 图片列表
      goods: null, // 商品信息
      isGoods: true, // 是否显示商品弹窗
      // 取消底部
      emptybottom: false,
      // #ifndef H5
      RECORDER: uni.getRecorderManager(), // 录音元素
      // #endif
      isVoice: false, // 录音模式
      voiceTis: "按住 说话", // 录音按钮文字
      recordTis: "手指上滑 取消发送", // 录音提示
      recording: false, // 是否录音中
      willStop: false, // 录音取消发送
      initPoint: { identifier: 0, Y: 0 }, // 触摸录音时位置
      recordTimer: null, // 录音定时器
      recordLength: 0, // 录音时长
      //播放语音相关参数
      AUDIO: uni.createInnerAudioContext(), // 音频元素
      playMsgid: null, // 播放音频ID
      // 抽屉参数
      popupLayerClass: false,
      // more参数
      hideMore: true,
      //表情定义
      TabCur: "默认",
      hideEmoji: true,
      emojiList: this.emojiData(),
      Sysmodel: uni.getSystemInfoSync().model,
    };
  },
  onLoad(option) {
    // 判断是否通过商品进来
    if (option.hasOwnProperty("goods")) {
      this.goods = JSON.parse(option.goods);
      setTimeout(() => {
        this.isGoods = false;
      }, 5000);
    }
    let info = this.$getStorage("USER_INFO");
    this.user_id = info.user_id;
    this.avatar = info.avatar;
    this.nickname = info.nickname;

    // 临时关闭推送
    this.$store.commit("setIschat", { notice: false });
    // 查看权限 1.0.2升级 追加商家在线状态
    chatShopChat({
      id: option.shop_id,
      type: "chat",
    }).then((res) => {
      if (res.code == 1) {
        this.to_id = res.data.user_id;
        this.shop_id = res.data.id;
        // 新版新追加
        this.shop_name = res.data.shopname;
        this.shop_avatar = res.data.avatar;
        uni.setNavigationBarTitle({
          title: res.data.shopname + (res.data.isOnline == 1 ? "-在线" : "-离线"),
        });
        // 初始界面
        this.getMsgList(res.data.user_id);
      }
    });
    //语音自然播放结束
    this.AUDIO.onEnded((res) => {
      this.playMsgid = null;
    });
    // #ifndef H5
    //录音开始事件
    this.RECORDER.onStart((e) => {
      this.recordBegin(e);
    });
    //录音结束事件
    this.RECORDER.onStop((e) => {
      this.recordEnd(e);
    });
    // #endif
    // 监听服务消息
    uni.$on("onChat", this.onSend);
  },
  // 监听返回
  onUnload() {
    this.$store.dispatch("update", { type: "del", id: this.to_id });
    // 恢复全局监听
    this.$store.commit("setIschat", { notice: true, number: 0 });
  },
  onShow() {
    this.scrollTop = 9999999;
  },
  methods: {
    // 消息列表
    getMsgList(id) {
      uni.getStorage({
        key: "wanlchat:message_" + id,
        success: (res) => {
          var list = res.data;
          for (let i = 0; i < list.length; i++) {
            // 获取消息中的图片,并处理显示尺寸
            if (list[i].type == "chat" && list[i].message.type == "img") {
              list[i].message.content = this.setPicSize(list[i].message.content);
              this.msgImgList.push(list[i].message.content.url);
            }
            // 获取消息中表情，并处理为图片
            if (list[i].type == "chat" && list[i].message.type == "text") {
              list[i].message.content.text = this.replaceEmoji(
                list[i].message.content.text
              );
            }
          }
          this.msgList = list;
          // 滚动到底部
          this.$nextTick(() => {
            this.scrollTop = 9999;
            this.$nextTick(() => {
              this.scrollAnimation = true;
            });
          });
        },
      });
    },
    // 接受本地消息
    onChat(msg) {
      if (msg.type == "system") {
        if (msg.msg.type == "text") {
          this.addSystemTextMsg(msg);
        }
      } else if (msg.type == "chat") {
        // 用户消息
        if (msg.message.type == "text") {
          this.addTextMsg(msg);
        }
        if (msg.message.type == "voice") {
          this.addVoiceMsg(msg);
        }
        if (msg.message.type == "img") {
          this.addImgMsg(msg);
        }
        if (msg.message.type == "goods") {
          this.addGoodsMsg(msg);
        }
      }
      // 滚动到底
      this.$nextTick(() => {
        this.scrollToView = "msg" + msg.id;
      });
    },
    // 接受在线消息
    onSend(msg) {
      if (msg.form.id == this.to_id) {
        if (msg.type == "system") {
          if (msg.msg.type == "text") {
            this.addSystemTextMsg(msg);
          }
        } else if (msg.type == "chat") {
          // 用户消息
          if (msg.message.type == "text") {
            this.addTextMsg(msg);
          }
          if (msg.message.type == "voice") {
            this.addVoiceMsg(msg);
          }
          if (msg.message.type == "img") {
            this.addImgMsg(msg);
          }
          if (msg.message.type == "goods") {
            this.addGoodsMsg(msg);
          }
        }
        // 滚动到底
        this.$nextTick(() => {
          this.scrollToView = "msg" + msg.id;
        });
      }
    },
    // 发送消息
    sendMsg(content, type) {
      let lastid = 1;
      if (this.msgList.length) {
        lastid = this.msgList[this.msgList.length - 1].id;
        lastid++;
      }
      let data = {
        id: lastid,
        type: "chat",
        to_id: this.to_id,
        form: {
          id: this.user_id, //本人
          avatar: this.avatar,
          name: this.nickname,
        },
        message: {
          type: type,
          content: content,
        },
        createtime: parseInt(new Date().getTime() / 1000),
      };
      // 深拷贝移除数据绑定
      this.onChat(JSON.parse(JSON.stringify(data)));
      // 更新列表
      this.$store.dispatch("update", {
        type: "send",
        data: data,
        shop: {
          id: this.shop_id,
          user_id: this.to_id,
          name: this.shop_name,
          avatar: this.shop_avatar,
        },
      });
      // 发送消息
      chatSend(data).then((res) => {
        if (res.code == 1) {
          this.$setChat(data, "send");
        }
      });
    },
    // 添加文字消息到列表
    addTextMsg(msg) {
      msg.message.content.text = this.replaceEmoji(msg.message.content.text);
      this.msgList.push(msg);
    },
    // 添加语音消息到列表
    addVoiceMsg(msg) {
      this.msgList.push(msg);
    },
    // 添加图片消息到列表
    addImgMsg(msg) {
      msg.message.content = this.setPicSize(msg.message.content);
      this.msgImgList.push(msg.message.content.url);
      this.msgList.push(msg);
    },
    // 添加商品消息到列表
    addGoodsMsg(msg) {
      this.msgList.push(msg);
    },
    // 添加系统文字消息到列表
    addSystemTextMsg(msg) {
      this.msgList.push(msg);
    },
    // 表情数据
    emojiData() {
      var groups = {},
        categories = [],
        map = {};
      emotions.forEach((emotion) => {
        var cate = emotion.category.length > 0 ? emotion.category : "默认";
        if (!groups[cate]) {
          groups[cate] = [];
          categories.push(cate);
        }
        groups[cate].push(emotion);
        map[emotion.phrase] = emotion.icon;
      });
      return { groups, categories, map };
    },
    //替换表情符号为图片
    replaceEmoji(str) {
      // 这里处理 链接   换行符
      let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
        return '<img src="' + this.emojiList.map[item] + '" width="18rpx">';
      });
      return replacedStr.replace(/(\r\n)|(\n)/g, "<br>");
    },
    // 表情tab
    tabSelect(e) {
      this.TabCur = e.currentTarget.dataset.id;
    },
    //触发滑动到顶部(加载历史信息记录)
    loadHistory(e) {
      // 说明加载过一次，并且没有任何记录了
      if (this.reload) return;
      if (this.isHistoryLoading) return;
      this.isHistoryLoading = true; //参数作为进入请求标识，防止重复请求
      this.scrollAnimation = false; //关闭滑动动画
      let view_id = this.msgList[0].id; //记住第一个信息ID
      //请求历史记录效果
      chatHistory({
        to_id: this.to_id,
        page: this.current_page,
      })
        .then((res) => {
          if (res.code == 1) {
            // 消息列表
            let list = res.data.data;
            // 获取消息中的图片,并处理显示尺寸
            for (let i = 0; i < list.length; i++) {
              if (list[i].type == "chat" && list[i].message.type == "img") {
                list[i].message.content = this.setPicSize(list[i].message.content);
                this.msgImgList.unshift(list[i].message.content.url);
              }
              // 获取消息中表情，并处理为图片
              if (list[i].type == "chat" && list[i].message.type == "text") {
                list[i].message.content.text = this.replaceEmoji(
                  list[i].message.content.text
                );
              }
            }
            list.sort((a, b) => {
              return a.updatetime - b.updatetime;
            });
            this.msgList = res.data.current_page == 1 ? list : list.concat(this.msgList);
            //这段代码很重要，不然每次加载历史数据都会跳到顶部
            this.$nextTick(() => {
              this.scrollToView = "msg" + view_id;
              this.$nextTick(() => {
                this.scrollAnimation = true; //恢复滚动动画
              });
            });
            // 判断尾页
            if (res.data.current_page == res.data.last_page) {
              // 下次不允许下拉加载数据了
              this.reload = true;
            } else {
              this.current_page = res.data.current_page + 1;
            }
          }
        })
        .finally(() => {
          this.isHistoryLoading = false;
          console.log("停止加载", this.isHistoryLoading);
        });
    },

    //处理图片尺寸，如果不处理宽高，新进入页面加载图片时候会闪
    setPicSize(content) {
      // 让图片最长边等于设置的最大长度，短边等比例缩小，图片控件真实改变，区别于aspectFit方式。
      let maxW = uni.upx2px(350); //350是定义消息图片最大宽度
      let maxH = uni.upx2px(350); //350是定义消息图片最大高度
      if (content.w > maxW || content.h > maxH) {
        let scale = content.w / content.h;
        content.w = scale > 1 ? maxW : maxH * scale;
        content.h = scale > 1 ? maxW / scale : maxH;
      }
      return content;
    },
    //更多功能(点击+弹出)
    showMore() {
      this.isVoice = false;
      this.hideEmoji = true;
      if (this.hideMore) {
        this.hideMore = false;
        this.openDrawer();
      } else {
        this.hideDrawer();
      }
    },
    // 打开抽屉
    openDrawer() {
      this.emptybottom = true;
      this.popupLayerClass = true;
    },
    // 隐藏抽屉
    hideDrawer() {
      this.emptybottom = false;
      this.popupLayerClass = false;
      setTimeout(() => {
        this.hideMore = true;
        this.hideEmoji = true;
      }, 150);
    },
    //选照片 or 拍照
    getImage(type) {
      this.hideDrawer();
      uni.chooseImage({
        sourceType: [type],
        sizeType: ["original", "compressed"], //可以指定是原图还是压缩图，默认二者都有
        success: (res) => {
          res.tempFilePaths.forEach((i) => {
            // 读取图片宽高
            uni.getImageInfo({
              src: i,
              success: (image) => {
                commonUpload(i).then((updata) => {
                  if (updata.code == 1) {
                    let obj = {
                      url: updata.data.fullurl,
                      w: image.width,
                      h: image.height,
                    };
                    this.sendMsg(obj, "img");
                  }
                });
              },
            });
          });
        },
      });
    },
    // 预览图片
    showPic(message) {
      uni.previewImage({
        indicator: "none",
        current: message.content.url,
        urls: this.msgImgList,
      });
    },
    // 选择表情
    chooseEmoji() {
      this.hideMore = true;
      if (this.hideEmoji) {
        this.hideEmoji = false;
        this.openDrawer();
      } else {
        this.hideDrawer();
      }
    },
    //添加表情
    addEmoji(em) {
      this.textMsg += em;
    },
    //获取焦点，如果不是选表情ing,则关闭抽屉
    textareaFocus() {
      this.emptybottom = true;
      this.closeTips();
      if (this.popupLayerClass && this.hideMore == false) {
        this.hideDrawer();
      }
    },
    // 失去焦点
    textareaBlur() {
      this.emptybottom = false;
    },

    // 发送文字消息
    sendText() {
      this.hideDrawer(); //隐藏抽屉
      if (!this.textMsg) {
        return;
      }
      let msg = { text: this.textMsg };
      this.sendMsg(msg, "text");
      this.textMsg = ""; //清空输入框
    },
    // 发送商品消息
    sendGoods(data) {
      this.sendMsg(data, "goods");
      this.closeTips();
    },
    // 关闭提示窗口
    closeTips() {
      this.isGoods = false;
    },
    // 播放语音
    playVoice(row) {
      this.playMsgid = row.id;
      this.AUDIO.src = row.message.content.url;
      this.$nextTick(() => {
        this.AUDIO.play();
      });
    },
    // 录音开始
    voiceBegin(e) {
      if (e.touches.length > 1) {
        return;
      }
      this.initPoint.Y = e.touches[0].clientY;
      this.initPoint.identifier = e.touches[0].identifier;
      this.RECORDER.start({ format: "mp3" }); //录音开始,
    },
    //录音开始UI效果
    recordBegin(e) {
      this.recording = true;
      this.voiceTis = "松开 结束";
      this.recordLength = 0;
      this.recordTimer = setInterval(() => {
        this.recordLength++;
      }, 1000);
    },
    // 录音被打断
    voiceCancel() {
      this.recording = false;
      this.voiceTis = "按住 说话";
      this.recordTis = "手指上滑 取消发送";
      this.willStop = true; //不发送录音
      this.RECORDER.stop(); //录音结束
    },
    // 录音中(判断是否触发上滑取消发送)
    voiceIng(e) {
      if (!this.recording) return;
      let touche = e.touches[0];
      //上滑一个导航栏的高度触发上滑取消发送
      if (this.initPoint.Y - touche.clientY >= uni.upx2px(200)) {
        this.willStop = true;
        this.recordTis = "松开手指 取消发送";
      } else {
        this.willStop = false;
        this.recordTis = "手指上滑 取消发送";
      }
    },
    // 结束录音
    voiceEnd(e) {
      if (!this.recording) return;
      this.recording = false;
      this.voiceTis = "按住 说话";
      this.recordTis = "手指上滑 取消发送";
      this.RECORDER.stop(); //录音结束
    },
    //录音结束(回调文件)
    recordEnd(e) {
      clearInterval(this.recordTimer);
      if (!this.willStop) {
        commonUpload(e.tempFilePath).then((res) => {
          if (res.code == 1) {
            let msg = { length: 0, url: res.data.fullurl };
            msg.length = this.recordLength % 60;
            if (msg.length > 0) {
              this.sendMsg(msg, "voice");
            }
          }
        });
      } else {
        console.log("取消发送录音");
      }
      this.willStop = false;
    },
    // 切换语音/文字输入模式
    switchVoice() {
      this.hideDrawer();
      this.isVoice = this.isVoice ? false : true;
    },
    // 跳转商品
    onGoods(id) {
      uni.navigateTo({ url: `/pages/mall/goodsDetail?id=${id}` });
    },
    discard() {
      return;
    },
  },
};
</script>
<style lang="scss" scoped>
.cu-btn {
  font-size: 12px;
  border-radius: 18px;
  height: 30px;
  color: #fff;
  background-color: #fe6600;
}
.chatTips {
  display: inline-flex;
  align-items: center;
  position: absolute;
  z-index: 101;
  right: 10px;
  background-color: #fff;
  padding: 20rpx;
  left: 10px;
  bottom: 120rpx;
  border-radius: 10px;
  bottom: calc(120rpx + env(safe-area-inset-bottom));
  image {
    width: 100rpx;
    height: 100rpx;
    margin-right: 20rpx;
    border-radius: 10rpx;
    flex-shrink: 0;
  }
  .details {
    width: calc(100% - 100rpx - 20rpx);
    display: flex;
    justify-content: space-between;
    flex-direction: column;
    > view {
      display: flex;
      justify-content: space-between;
      align-items: center;
      &:nth-child(2) {
        margin-top: 20rpx;
      }
    }
  }
}

.cu-chat {
  position: absolute;
  top: 0;
  bottom: 100rpx;
  bottom: calc(env(safe-area-inset-bottom) + 100rpx);
  background-color: #ececec;
  .cu-item {
    display: flex;
    padding: 15px 15px 36px;
    position: relative;
    .cu-avatar {
      font-variant: small-caps;
      margin: 0;
      padding: 0;
      display: inline-flex;
      text-align: center;
      justify-content: center;
      align-items: center;
      color: #ffffff;
      white-space: nowrap;
      position: relative;
      width: 41px;
      height: 41px;
      background-size: cover;
      background-position: center;
      vertical-align: middle;
      font-size: 1.5em;
      border-radius: 10rpx;
    }
    .date {
      position: absolute;
      font-size: 12px;
      color: #8799a3;
      width: calc(100% - 166px);
      bottom: 10px;
      left: 83px;
    }
  }
  .self {
    justify-content: flex-end;
    text-align: right;
    .main .content::after {
      left: auto !important;
      right: -5px !important;
    }
  }
  .cu-info {
    margin: 20rpx auto;
    font-size: 24rpx;
    padding: 8rpx 12rpx;
    background-color: rgba(0, 0, 0, 0.2);
    border-radius: 6rpx;
    color: #ffffff;
    text-align: center;
    max-width: 300rpx;
    line-height: 1.4;
  }
}
.cu-chat .cu-item > .main {
  max-width: calc(100% - 135px);
  margin: 0 20px;
  display: flex;
  align-items: center;
  .content {
    padding: 10px;
    border-radius: 3px;
    display: inline-flex;
    max-width: 100%;
    align-items: center;
    font-size: 15px;
    position: relative;
    min-height: 20px;
    min-width: 18px;
    line-height: 20px;
    text-align: left;
    &:not([class*="bg-"]) {
      background-color: #ffffff;
      color: #333333;
    }
    &::after {
      content: "";
      top: 14px;
      left: -5px;
      right: initial;
      -webkit-transform: rotate(45deg);
      transform: rotate(45deg);
      position: absolute;
      z-index: 100;
      display: inline-block;
      overflow: hidden;
      width: 12px;
      height: 12px;
      background-color: inherit;
      border-radius: 1px;
    }
    .text-name {
      font-size: 15px;
      color: #333;
    }
  }
  .bg-green {
    background-color: #39b54a;
    color: #ffffff;
  }
  .action {
    padding: 0 15px;
    display: flex;
    align-items: center;
    color: #8799a3;
    font-weight: bold;
    padding-right: 1px;
  }
}
.text-price {
  margin-top: 5px;
  margin-bottom: 5px;
  font-size: 16px;
  color: #fe6600;
  &::before {
    content: "¥";
    font-size: 80%;
    margin-right: 2px;
  }
}
.cu-chat .cu-item > .main.goods .content,
.cu-chat .cu-item > .main.order .content {
  display: block;
}
.cu-chat .cu-item > .main.order {
  max-width: calc(100% - 200rpx);
}
.cu-chat .cu-item > .main.order .product {
  background-color: #f9f9f9;
}
.cu-chat .cu-item > .main.order .product .item {
  display: flex;
  justify-content: space-between;
  margin-bottom: 25rpx;
}
.cu-chat .cu-item > .main.order .product .item:last-of-type {
  margin-bottom: 0;
}

.cu-chat .cu-item > .main.order .product .item .image,
.product .item .image image {
  width: 100rpx;
  height: 100rpx;
  border-radius: 10rpx;
}

.cu-chat .cu-item > .main.order .product .item .details {
  display: flex;
  flex-wrap: wrap;
  width: calc(100% - 120rpx);
  align-content: space-between;
}

.opmenu {
  display: flex;
  flex-wrap: wrap;
  margin-top: 2rpx;
  color: #4c4c4c;
  .box {
    padding-top: 35rpx;
    padding-left: 50rpx;
    text-align: center;
    .icon {
      height: 120rpx;
      width: 120rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      justify-items: center;
      background-color: #ffffff;
      border-radius: 20rpx;
      font-size: 68rpx;
      margin-bottom: 10rpx;
    }
  }
}
.emptybottom {
  padding-bottom: 0 !important;
}
.hidden {
  display: none !important;
}
.cu-chat .cu-item > .main .content {
  font-size: 30rpx;
  border-radius: 17rpx;
}
.cu-chat .cu-item [class*="wlIcon-"] {
  font-size: 34rpx;
}
.showLayer {
  transform: translate3d(0, -480rpx, 0);
}
.popup-layer {
  transition: all 0.15s linear;
  width: 100%;
  height: 480rpx;
  background-color: #f5f5f5;
  position: fixed;
  z-index: 2000;
  top: 100%;
  .emoji {
    .emojinav {
      background-color: #f8f8f8;
      .item {
        display: flex;
        align-items: center;
        height: 100rpx;
        padding-left: 10rpx;
        > view {
          margin: 0 25rpx;
          width: 60rpx;
          height: 60rpx;
          border-radius: 18rpx;
          background-repeat: no-repeat;
          background-size: 80%;
          background-position: center;
        }
        .emojibg {
          background-color: #dedede;
        }
      }
    }
    .subject {
      height: 380rpx;
      background-color: #f1f1f1;
      .item {
        padding: 25rpx;
        display: flex;
        flex-wrap: wrap;
        margin-bottom: 15px;
        text-align: center;
        > view {
          background-repeat: no-repeat;
          background-size: 56%;
          background-position: center;
          width: 12.5%;
          height: 100rpx;
        }
      }
    }
  }
}

.input-box {
  width: 100%;
  min-height: 100rpx;
  padding-bottom: env(safe-area-inset-bottom);
  background-color: #f2f2f2;
  display: flex;
  align-items: flex-end;
  position: fixed;
  z-index: 2000;
  bottom: -2rpx;
  transition: all 0.15s linear;
  .showLayer {
    transform: translate3d(0, -480rpx, 0);
  }
  .voice,
  .more {
    flex-shrink: 0;
    width: 90rpx;
    height: 100rpx;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .send {
    flex-shrink: 0;
    width: 90rpx;
    height: 100rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    .btn {
      width: 110rpx;
      height: 70rpx;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 16rpx;
      font-size: 32rpx;
    }
    .fasong {
      font-size: 24rpx;
      padding: 12rpx 20rpx;
      color: #fff;
      background-color: #d6d6d6;
      border-radius: 10rpx;
    }
  }
  .textbox {
    width: 100%;
    .voice-mode {
      width: calc(100% - 2upx);
      height: 80rpx;
      margin: 10rpx 0;
      border-radius: 16rpx;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 28rpx;
      background-color: #fff;
      color: #555;
      .recording {
        background-color: #e5e5e5;
      }
    }
  }
  .text-mode {
    width: 100%;
    min-height: 80rpx;
    margin: 10rpx 0;
    display: flex;
    background-color: #ffffff;
    border-radius: 16rpx;
    .box {
      width: 100%;
      padding-left: 30rpx;
      min-height: 80rpx;
      display: flex;
      align-items: center;
      textarea {
        width: 100%;
      }
    }
    .em {
      flex-shrink: 0;
      width: 80rpx;
      padding-left: 10rpx;
      height: 80rpx;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
}
.input-box [class*="wlIcon-"] {
  font-size: 50rpx;
  color: #323232;
}

.record {
  width: 39vw;
  height: 39vw;
  position: fixed;
  top: 35%;
  left: 30%;
  background-color: rgba(0, 0, 0, 0.8);
  border-radius: 40rpx;
  .ing {
    width: 100%;
    height: 30vw;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .ing [class*="wlIcon"] {
    background-image: linear-gradient(to bottom, #ffffff, #565656 50%);
    background-size: 100% 200%;
    animation: volatility 1.5s ease-in-out -1.5s infinite alternate;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    font-size: 140rpx;
    padding-top: 40rpx;
    color: #f09b37;
  }
  .tis {
    width: 100%;
    height: 10vw;
    display: flex;
    justify-content: center;
    font-size: 24rpx;
    color: #fff;
    .change {
      color: #f09b37;
    }
  }
  .cancel {
    width: 100%;
    height: 30vw;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .cancel [class*="wlIcon"] {
    color: #fff;
    font-size: 150rpx;
  }
}
@keyframes volatility {
  0% {
    background-position: 0% 130%;
  }
  20% {
    background-position: 0% 150%;
  }
  30% {
    background-position: 0% 155%;
  }
  40% {
    background-position: 0% 160%;
  }
  50% {
    background-position: 0% 145%;
  }
  70% {
    background-position: 0% 150%;
  }
  80% {
    background-position: 0% 170%;
  }
  90% {
    background-position: 0% 160%;
  }
  100% {
    background-position: 0% 135%;
  }
}

.content {
  width: 100%;
}
page {
  background-color: #ececec;
}
.edgeInsetTop {
  height: var(--window-top);
}
</style>
